#pragma once
#include <memory>
#include <vector>
#include <string_view>

namespace mylog
{
    struct LogMessage;

    class LogFormatter
    {
    public:
        using ptr = std::shared_ptr<LogFormatter>;

        /**
         * @brief LogFormatter构造函数
         * @param[in] pattern 格式模板
         * %P 日志级别
         * %F 文件名
         * %L 行号
         * %C 日志名称
         * %M 消息
         * %T 线程ID
         * %D{时间格式} 时间。时间格式类似于{%Y-%m-%d %H:%M:%S}
         * %t 制表符
         * %n 换行符
         * 
         * 默认的日志格式为: "[%D{%Y-%m-%d %H:%M:%S}] [%T] [%P] [%C] [%F:%L] %M%n" 
         * 若解析用户自定义pattern时出现错误，则会使用将pattern设置为默认的格式
         */
        LogFormatter(std::string_view pattern);

        /**
         * @brief 按照pattern输出格式化的日志数据字符串
         * @param message 日志数据
         * @return 格式化后的日志字符串
         */
        std::string format(std::shared_ptr<LogMessage> message);

        /**
         * @return 日志输出格式
         */
        std::string getPattern() const;
    public:
        class FormatItem
        {
        public:
            using ptr = std::shared_ptr<LogFormatter::FormatItem>;
            virtual ~FormatItem() = default;
            virtual void format(std::ostream& os, std::shared_ptr<LogMessage> message) = 0;
        };

    private:
        // 根据pattern_初始化format_items_用于后续的日志格式化
        void initFormatItems();

        // 日志格式模板
        std::string pattern_;

        // 日志格式解析后的格式输出项
        std::vector<FormatItem::ptr> format_items_;

        // 默认格式
        const std::string DEFAULT_PATTERN = "[%D{%Y-%m-%d %H:%M:%S}] [%T] [%P] [%C] [%F:%L] %M%n";
    };

} // namespace mylog